package com.coursehub.gateway.config;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cloud.gateway.filter.GatewayFilter;
import org.springframework.cloud.gateway.filter.factory.AbstractGatewayFilterFactory;
import org.springframework.cloud.gateway.route.RouteLocator;
import org.springframework.cloud.gateway.route.builder.RouteLocatorBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.stereotype.Component;
import reactor.core.publisher.Mono;
import com.coursehub.gateway.filter.JwtAuthenticationFilter;

/**
 * API网关配置类
 * 
 * 提供自定义路由配置和过滤器
 */
@Configuration
public class GatewayConfig {
    
    private static final Logger log = LoggerFactory.getLogger(GatewayConfig.class);

    /**
     * 自定义路由配置
     * 这里可以通过代码方式配置路由，作为application.yml配置的补充
     */
    @Bean
    public LoggingGatewayFilterFactory loggingGatewayFilterFactory() {
        return new LoggingGatewayFilterFactory();
    }

    @Bean
    public RouteLocator customRouteLocator(RouteLocatorBuilder builder, LoggingGatewayFilterFactory loggingGatewayFilterFactory, JwtAuthenticationFilter jwtAuthenticationFilter) {
        return builder.routes()
            // 用户服务路由 - 优先级最高
            .route("user-service-api", r -> r
                .path("/api/users/**")
                .filters(f -> f
                    .addRequestHeader("X-Gateway-Source", "api-gateway")
                    .addRequestHeader("X-Service-Type", "microservice")
                    .filter(loggingGatewayFilterFactory.apply(new LoggingGatewayFilterFactory.Config()))
                    .filter(jwtAuthenticationFilter.apply(new JwtAuthenticationFilter.Config()))
                )
                .uri("lb://user-service")
            )
            
            // 认证服务路由
            .route("auth-service-api", r -> r
                .path("/api/auth/**")
                .filters(f -> f
                    .addRequestHeader("X-Gateway-Source", "api-gateway")
                    .addRequestHeader("X-Service-Type", "microservice")
                    .filter(loggingGatewayFilterFactory.apply(new LoggingGatewayFilterFactory.Config()))
                    .filter(jwtAuthenticationFilter.apply(new JwtAuthenticationFilter.Config()))
                )
                .uri("lb://user-service")
            )
            
            // 单体系统兜底路由 - 优先级最低
            .route("monolith-fallback", r -> r
                .path("/api/**")
                .filters(f -> f
                    .addRequestHeader("X-Gateway-Source", "api-gateway")
                    .addRequestHeader("X-Service-Type", "monolith")
                    .filter(loggingGatewayFilterFactory.apply(new LoggingGatewayFilterFactory.Config()))
                    .filter(jwtAuthenticationFilter.apply(new JwtAuthenticationFilter.Config()))
                )
                .uri("http://localhost:8080")
            )
            
            .build();
    }

    /**
     * 自定义日志过滤器工厂
     */
    @Component
    public static class LoggingGatewayFilterFactory extends AbstractGatewayFilterFactory<LoggingGatewayFilterFactory.Config> {
        
        private static final Logger log = LoggerFactory.getLogger(LoggingGatewayFilterFactory.class);

        public LoggingGatewayFilterFactory() {
            super(Config.class);
        }

        @Override
        public GatewayFilter apply(Config config) {
            return (exchange, chain) -> {
                ServerHttpRequest request = exchange.getRequest();
                String path = request.getURI().getPath();
                String method = request.getMethod().toString();
                String serviceType = request.getHeaders().getFirst("X-Service-Type");
                
                log.info("网关路由请求: {} {} -> 目标: {}", method, path, serviceType);
                
                return chain.filter(exchange).then(Mono.fromRunnable(() -> {
                    int statusCode = exchange.getResponse().getStatusCode().value();
                    log.info("网关响应: {} {} -> 状态码: {}", method, path, statusCode);
                }));
            };
        }

        public static class Config {
            // 配置类，可以添加自定义配置参数
        }
    }
}